home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
magazine
/
drdobbs
/
1991
/
05
/
d_flat
/
textbox.c
< prev
next >
Wrap
Text File
|
1991-02-19
|
11KB
|
457 lines
/* ------------- textbox.c ------------ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include "dflat.h"
static char *GetTextLine(WINDOW wnd, int selection);
static int HScrolling = FALSE;
static int VScrolling = FALSE;
int TextBoxProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
{
int mx = (int) p1 - GetLeft(wnd);
int my = (int) p2 - GetTop(wnd);
switch (msg) {
case CREATE_WINDOW:
wnd->wlines = wnd->wtop = wnd->wleft =
wnd->textlen = wnd->textwidth = 0;
wnd->text = NULL;
wnd->HScrollBox = wnd->VScrollBox = 1;
ClearBlock(wnd);
break;
case ADDTEXT: {
/* ======== need to assure that length !> 64K ======= */
int adln = strlen((char *)p1)+2;
if (wnd->text != NULL) {
int txln = strlen(wnd->text);
if (txln+adln > wnd->textlen) {
wnd->text = realloc(wnd->text, txln+adln);
wnd->textlen = txln+adln-1;
}
}
else {
wnd->text = malloc(adln);
*wnd->text = '\0';
wnd->textlen = adln-1;
}
strcat(wnd->text, (char*) p1);
strcat(wnd->text, "\n");
wnd->wlines++;
wnd->textwidth = max(adln, wnd->textwidth);
break;
}
case SETTEXT: {
char *cp, *cp1;
SendMessage(wnd, CLEARTEXT, 0, 0);
wnd->text = cp = cp1 = (void *) p1;
wnd->textlen = max(strlen(cp)+1, (int) p2);
while ((cp = strchr(cp, '\n')) != NULL) {
wnd->wlines++;
cp++;
wnd->textwidth = max(wnd->textwidth, (int)(cp-cp1));
cp1 = cp;
}
break;
}
case CLEARTEXT:
if (wnd->text != NULL)
free(wnd->text);
wnd->text = NULL;
wnd->textlen = 0;
wnd->wlines = 0;
wnd->textwidth = 0;
wnd->wtop = wnd->wleft = 0;
ClearBlock(wnd);
break;
case SETFOCUS:
if (!p1 && isMultiLine(wnd))
ClearBlock(wnd);
break;
case KEYBOARD:
if (WindowMoving || WindowSizing)
break;
switch ((int) p1) {
case UP:
if (wnd->wtop)
SendMessage(wnd, SCROLL, FALSE, 0);
return TRUE;
case DN:
if (wnd->wtop+ClientHeight(wnd) < wnd->wlines)
SendMessage(wnd, SCROLL, TRUE, 0);
return TRUE;
case FWD:
SendMessage(wnd, HORIZSCROLL, TRUE, 0);
return TRUE;
case BS:
SendMessage(wnd, HORIZSCROLL, FALSE, 0);
return TRUE;
case PGUP:
if (wnd->wtop) {
wnd->wtop -= ClientHeight(wnd);
if (wnd->wtop < 0)
wnd->wtop = 0;
SendMessage(wnd, PAINT, 0, 0);
return TRUE;
}
return TRUE;
case PGDN:
if (wnd->wtop+ClientHeight(wnd) < wnd->wlines) {
wnd->wtop += ClientHeight(wnd);
if (wnd->wtop > wnd->wlines-ClientHeight(wnd))
wnd->wtop = wnd->wlines-ClientHeight(wnd);
SendMessage(wnd, PAINT, 0, 0);
return TRUE;
}
return TRUE;
case HOME:
if (wnd->wtop || wnd->wleft) {
wnd->wtop = wnd->wleft = 0;
SendMessage(wnd, PAINT, 0, 0);
}
return TRUE;
case END:
if (wnd->wtop+ClientHeight(wnd) < wnd->wlines) {
wnd->wtop = wnd->wlines-ClientHeight(wnd);
wnd->wleft = 0;
SendMessage(wnd, PAINT, 0, 0);
}
return TRUE;
default:
break;
}
break;
case LEFT_BUTTON:
if (WindowSizing || WindowMoving)
return FALSE;
if (TestAttribute(wnd, VSCROLLBAR) && (VScrolling ||
mx == WindowWidth(wnd)-1)) {
/* -------- in the right border ------- */
if (my == 0 || my == ClientHeight(wnd)+1)
/* ------ above or below the scroll bar ---- */
break;
/* ---------- in the scroll bar ----------- */
VScrolling = TRUE;
if (my == 1) {
/* -------- top scroll button --------- */
SendMessage(wnd, SCROLL, FALSE, 0);
return TRUE;
}
if (my == ClientHeight(wnd)) {
/* -------- bottom scroll button --------- */
SendMessage(wnd, SCROLL, TRUE, 0);
return TRUE;
}
if (my-1 != wnd->VScrollBox) {
int dir = my-1 > wnd->VScrollBox;
while (dir ? (my-1 > wnd->VScrollBox) :
(my-1 < wnd->VScrollBox)) {
if (!SendMessage(NULLWND, TESTMOUSE, 0, 0))
break;
SendMessage(wnd, SCROLL, dir, 0);
}
return TRUE;
}
}
if (TestAttribute(wnd, HSCROLLBAR) &&
(HScrolling || my == WindowHeight(wnd)-1)) {
/* -------- in the bottom border ------- */
if (mx == 0 || my == ClientWidth(wnd)+1)
/* ------ outside the scroll bar ---- */
break;
HScrolling = TRUE;
if (mx == 1) {
SendMessage(wnd, HORIZSCROLL, FALSE, 0);
return TRUE;
}
if (mx == WindowWidth(wnd)-2) {
SendMessage(wnd, HORIZSCROLL, TRUE, 0);
return TRUE;
}
if (mx-1 != wnd->HScrollBox) {
int dir = mx-1 > wnd->HScrollBox;
while (dir ? (mx-1 > wnd->HScrollBox) :
(mx-1 < wnd->HScrollBox)) {
if (!SendMessage(NULLWND, TESTMOUSE, 0, 0))
break;
SendMessage(wnd, HORIZSCROLL, dir, 0);
}
return TRUE;
}
}
break;
case BUTTON_RELEASED:
HScrolling = VScrolling = FALSE;
break;
case SCROLL:
if (isVisible(wnd)) {
if (p1 == 0) {
if (wnd->wtop == 0)
return FALSE;
}
else if (wnd->wtop+ClientHeight(wnd) >= wnd->wlines)
return FALSE;
if (p1)
wnd->wtop++;
else
--wnd->wtop;
SendMessage(wnd, PAINT, 0, 0);
return TRUE;
}
break;
case HORIZSCROLL:
if (p1 == 0 && wnd->wleft == 0)
return FALSE;
if (p1) {
if (wnd->wleft + ClientWidth(wnd)-1 >= wnd->textwidth)
return FALSE;
wnd->wleft++;
}
else
--wnd->wleft;
SendMessage(wnd, PAINT, 0, 0);
return TRUE;
case PAINT:
if (isVisible(wnd) && wnd->wlines) {
RECT rc;
int y;
if ((RECT *)p1 == NULL)
rc = SetRect(0, 0, ClientWidth(wnd)-1,
ClientHeight(wnd)-1);
else
rc = *(RECT *)p1;
for (y = RectTop(rc); y <= RectBottom(rc); y++) {
if (y < wnd->wlines-wnd->wtop)
WriteTextLine(wnd, &rc, y, FALSE);
else {
char line[SCREENWIDTH];
memset(line, ' ', sizeof line);
line[RectRight(rc)+1] = '\0';
SetStandardColor(wnd);
writeline(wnd, line+RectLeft(rc),
RectLeft(rc), y, FALSE);
}
}
if (TestAttribute(wnd, VSCROLLBAR)) {
int pagelen = wnd->wlines - ClientHeight(wnd);
int barlen = ClientHeight(wnd)-2;
int lines_tick;
if (pagelen < 1)
wnd->VScrollBox = 1;
else {
if (pagelen > barlen)
lines_tick = pagelen / barlen;
else
lines_tick = barlen / pagelen;
wnd->VScrollBox = 1 + (wnd->wtop / lines_tick);
if (wnd->VScrollBox > ClientHeight(wnd)-2 ||
wnd->wtop + ClientHeight(wnd) >= wnd->wlines)
wnd->VScrollBox = ClientHeight(wnd)-2;
}
SendMessage(wnd, BORDER, p1, 0);
}
if (TestAttribute(wnd, HSCROLLBAR)) {
int pagewidth = wnd->textwidth - ClientWidth(wnd);
int barlen = ClientWidth(wnd)-2;
int chars_tick;
if (pagewidth < 1)
wnd->HScrollBox = 1;
else {
if (pagewidth > barlen)
chars_tick = pagewidth / barlen;
else
chars_tick = barlen / pagewidth;
wnd->HScrollBox = 1 + (wnd->wleft / chars_tick);
if (wnd->HScrollBox > ClientWidth(wnd)-2 ||
wnd->wleft + ClientWidth(wnd) >= wnd->textwidth)
wnd->HScrollBox = ClientWidth(wnd)-2;
}
SendMessage(wnd, BORDER, p1, 0);
}
return FALSE;
}
break;
case CLOSE_WINDOW:
SendMessage(wnd, CLEARTEXT, 0, 0);
break;
default:
break;
}
return BaseWndProc(TEXTBOX, wnd, msg, p1, p2);
}
char *TextLine(WINDOW wnd, int selection)
{
char *cp = wnd->text;
if (selection == -1)
return NULL;
while (selection--) {
while (*cp != '\n')
cp++;
cp++;
}
return cp;
}
static char *GetTextLine(WINDOW wnd, int selection)
{
char *line;
int len = 0;
char *cp, *cp1;
cp = cp1 = TextLine(wnd, selection);
while (*cp && *cp != '\n') {
len++;
cp++;
}
line = malloc(len+6);
if (line != NULL) {
memmove(line, cp1, len);
line[len] = '\0';
}
return line;
}
void WriteTextLine(WINDOW wnd, RECT *rcc, int y, int reverse)
{
int len = 0;
int dif = 0;
char line[100];
RECT rc;
char *lp, *svlp;
int lnlen;
int i;
int trunc = FALSE;
lp = svlp = GetTextLine(wnd, wnd->wtop+y);
lnlen = LineLength(lp);
/* -------- insert block color change controls ------- */
if (BlockMarked(wnd)) {
int bbl = wnd->BlkBegLine;
int bel = wnd->BlkEndLine;
int bbc = wnd->BlkBegCol;
int bec = wnd->BlkEndCol;
int by = y+wnd->wtop;
if (bbl > bel) {
swap(bbl, bel);
swap(bbc, bec);
}
if (bbl == bel && bbc > bec)
swap(bbc, bec);
if (by >= bbl && by <= bel) {
/* ------ the block includes this line ----- */
int blkbeg = 0;
int blkend = lnlen;
if (!(by > bbl && by < bel)) {
/* --- the entire line is not in the block --- */
if (by == bbl)
/* ---- the block begins on this line ---- */
blkbeg = bbc;
if (by == bel)
/* ---- the block ends on this line ---- */
blkend = bec;
}
memmove(lp+blkend+1, lp+blkend, strlen(lp+blkend)+1);
lp[blkend] = RESETCOLOR;
memmove(lp+blkbeg+3, lp+blkbeg, strlen(lp+blkbeg)+1);
lp[blkbeg] = CHANGECOLOR;
SetReverseColor(wnd);
lp[blkbeg+1] = foreground | 0x80;
lp[blkbeg+2] = background | 0x80;
lnlen += 4;
}
}
for (i = 0; i < wnd->wleft+3; i++)
if (*(unsigned char *)(lp + i) == RESETCOLOR)
break;
if (i < wnd->wleft+3) {
if (wnd->wleft+4 > lnlen)
trunc = TRUE;
else
lp += 4;
}
else {
for (i = 0; i < wnd->wleft; i++) {
if (*(unsigned char *)(lp + i) == CHANGECOLOR) {
*(lp+wnd->wleft+2) = *(lp+i+2);
*(lp+wnd->wleft+1) = *(lp+i+1);
*(lp+wnd->wleft) = *(lp+i);
break;
}
}
}
if (!trunc) {
if (lnlen < wnd->wleft)
lnlen = 0;
else
lp += wnd->wleft;
if (rcc == NULL)
rc = SetRect(0, 0, ClientWidth(wnd)-1, ClientHeight(wnd)-1);
else
rc = *rcc;
if (y < rc.tp || y > rc.bt)
return;
if (lnlen > RectLeft(rc)) {
lp += RectLeft(rc);
lnlen = LineLength(lp);
len = min(lnlen, RectWidth(rc));
lnlen = LineLength(lp);
dif = strlen(lp) - lnlen;
len += dif;
if (len > 0)
strncpy(line, lp, len);
}
}
while (len < RectWidth(rc)+dif)
line[len++] = ' ';
line[len] = '\0';
dif = 0;
if (reverse) {
char *cp = line;
SetReverseColor(wnd);
while ((cp = strchr(cp, CHANGECOLOR)) != NULL) {
cp += 2;
*cp++ = background | 0x80;
}
if (*(unsigned char *)line == CHANGECOLOR)
dif = 3;
}
else
SetStandardColor(wnd);
writeline(wnd, line+dif, RectLeft(rc), y, FALSE);
if (svlp != NULL)
free(svlp);
}
void SetTextBlock(WINDOW wnd, int l1, int c1, int l2, int c2)
{
wnd->BlkBegLine = l1;
wnd->BlkBegCol = c1;
wnd->BlkEndLine = l2;
wnd->BlkEndCol = c2;
}